#pragma once
#include <iostream>
#include "../comm/log.hpp"
#include "../comm/util.hpp"
#include <unordered_map>
#include <vector>
#include <fstream>
#include <cstdlib>
#include <cassert>
#include <string>
#include <cassert>
namespace ns_model
{
    using namespace ns_log;
    using namespace ns_util;
    struct question
    {
        std::string number; // 题目编号，唯一
        std::string title;  // 题目的标题
        std::string star;   // 难度: 简单 中等 困难
        int cpu_limit;      // 题目的时间要求(S)
        int mem_limit;      // 题目的空间要去(KB)
        std::string desc;   // 题目的描述
        std::string header; // 题目预设给用户在线编辑器的代码
        std::string tail;   // 题目的测试用例，需要和header拼接，形成完整代码
    };
    const std::string questions_list = "./questions/questions.list";
    const std::string questions_path = "./questions/";
    class model
    {
    public:
        model()
        {
            assert(loadquestion(questions_list));
        }
        bool loadquestion(const std::string &question_list)
        {
            std::ifstream in(question_list);
            if (!in.is_open())
            {
                LOG(FATAL) << "加载题库失败" << std::endl;
                return false;
            }
            std::string line;
            while (getline(in, line))
            {
                std::vector<std::string> qs;
                FileUtil::splits(line, &qs, " ");
                if (qs.size() != 5)
                {
                    LOG(WARNING) << "加载部分题目失败, 请检查文件格式" << "\n";
                    continue;
                }
                question q;
                q.number = qs[0];
                q.title = qs[1];
                q.star = qs[2];
                q.cpu_limit = atoi(qs[3].c_str());
                q.mem_limit = atoi(qs[4].c_str());

                std::string path = questions_path;
                path += q.number;
                path += "/";

                FileUtil::ReadFile(path + "desc.txt", &(q.desc), true);
                FileUtil::ReadFile(path + "header.cpp", &(q.header), true);
                FileUtil::ReadFile(path + "tail.cpp", &(q.tail), true);

                questions.insert({q.number, q});
            }
            return true;
        }
        bool getallquestions(std::vector<question> *out)
        {
            if (questions.size() == 0)
            {
                LOG(ERROR) << "用户获取题库失败" << "\n";
                return false;
            }
            auto it = questions.begin();
            while (it != questions.end())
            {
                out->push_back(it->second);
                it++;
            }
            return true;
        }
        bool getonequestion(const std::string &num, question *q)
        {
            auto it = questions.find(num);
            if (it != questions.end())
            {
                *q = it->second;
                return true;
            }
            LOG(ERROR) << "用户获取题目失败, 题目编号: " << num << "\n";
            return false;
        }
        ~model() {}

    private:
        // 题号，题目的所有信息
        std::unordered_map<std::string, question> questions;
    };
}